<#
    .SYNOPSIS
    Pester test for Choco packages.

    .DESCRIPTION
    Basic tests such as install, uninstall, upgrade.
    Advanced tests per Choco validator.
    Out-of-the-box software is handled specially. There should be integration test of OS build. Install, Uninstall tests to be skipped in this script.

    .NOTES
    NAME: ChocoPackage.Test.ps1
    AUTHOR: Yunpeng
    LASTEDIT: 2023-10-04

    .LINK
    https://docs.chocolatey.org/en-us/community-repository/moderation/package-validator/rules/
    
    TODO: nuspec
#>

#Requires -Version 5.0
#Requires -RunAsAdministrator
#Requires -Modules @{ ModuleName = "Pester"; ModuleVersion = "5.5" }

param (
    [string]$packageID,
    [string]$packageVersion,
    [string]$packageSource = 'https://chocolatey.org/api/v2/'
)

BeforeAll {
    # Import the Pester module if not already loaded.
    # This section is not needed with existance of Requires statement.
    if (-not (Get-Module -Name Pester -ListAvailable)) {
        Install-Module -Name Pester -Force -Scope CurrentUser
    }
    Import-Module Pester

    # Define the out-of-the-box software list in array.
    $oobSoftwareSrv = @{
        #Others
        VMTools            = "vmtools"
        JiraAssetDiscovery = "jiradisc"
        #EUT
        Edge               = "Microsoft-Edge"
        # ESP
        XDR                = "xdr"
        Splunk             = "splunk"
        Sysmon             = "sysmon"
    }
    $oobSoftwarePC = @{
        #Others
        VMTools            = "vmtools"
        JiraAssetDiscovery = "jiradisc"
        #EUT
        Edge               = "Microsoft-Edge"
        AdobeReader        = "adobe-reader"
        # ESP
        XDR                = "xdr"
        Splunk             = "splunk"
        Sysmon             = "sysmon"
        DLP                = "dlp"
        DefendPoint        = "defendpoint"
    }

    if ((Get-CimInstance Win32_OperatingSystem).Caption.Split() -contains "server") {
        $oobSoftware = $oobSoftwareSrv
    }
    else { $oobSoftware = $oobSoftwarePC }

    if ($oobSoftware -contains $packageID) {
        Write-Host -Object "$packageID is one of out-of-the-box software.`nThere should be integration test of OS build.`nInstall, Uninstall tests to be skipped in this script."
        $skipInstallTest = $true
        $skipUninstallTest = $true
    }
}

# Test the installation of the Chocolatey package
Describe "Install $packageID" {
    It "Should install $packageID version $packageVersion" {
        Install-ChocolateyPackage -packageID $packageID -Version $packageVersion -Source $packageSource | Should -Not -Throw
    }

    It "Should verify that $packageID is installed" {
        Test-Path (Join-Path $env:ChocolateyLib\bin $packageID.exe) | Should -Be $true
    }
}

# Test the uninstallation of the Chocolatey package
Describe "Uninstall $packageID" {
    It "Should uninstall $packageID" {
        Uninstall-ChocolateyPackage -packageID $packageID -Version $packageVersion | Should -Not -Throw
    }

    It "Should verify that $packageID is not installed" {
        Test-Path (Join-Path $env:ChocolateyLib\bin $packageID.exe) | Should -Be $false
    }
}

# Test the upgrade of the Chocolatey package
Describe "Upgrade $packageID" {
    It "Should upgrade $packageID to the latest version" {
        Upgrade-ChocolateyPackage -packageID $packageID -Source $packageSource | Should -Not -Throw
    }

    It "Should verify that $packageID is upgraded" {
        $installedVersion = (Get-ChocolateyPackage $packageID).Version
        $installedVersion | Should -Be $packageVersion
    }
}

# Run the Pester tests
Invoke-Pester -Output Detailed
